﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;

namespace QueryZJK.Helpers
{
    public sealed class EnumHelper
    {
        #region ctor
        private EnumHelper()
        {
        }
        #endregion
        #region Methods

        #region Parse 
        /// <summary>
        /// 将字符串值转换为对应的枚举值 
        /// </summary>
        public static TEnum Parse<TEnum>(string value) where TEnum : struct, IComparable, IFormattable, IConvertible
        {//EnumHelper.Parse<Fabric>("cotton",false).Dump()
            return EnumHelper.Parse<TEnum>(value, true);
        }
        public static TEnum Parse<TEnum>(string value, bool ignoreCase) where TEnum : struct, IComparable, IFormattable, IConvertible
        {
            return (TEnum)Enum.Parse(typeof(TEnum), value, ignoreCase);
        }

        public static bool TryParse<TEnum>(string value, out TEnum returnedValue)
        {
            return EnumHelper.TryParse<TEnum>(value, true, out returnedValue);
        }
        public static bool TryParse<TEnum>(string value, bool ignoreCase, out TEnum returnedValue)
        {
            try
            {
                returnedValue = (TEnum)Enum.Parse(typeof(TEnum), value, ignoreCase);
                return true;
            }
            catch
            {
                returnedValue = default(TEnum);
                return false;
            }
        }
        #endregion

        /// <summary>
        /// Returns an enumerable collection of all values and descriptions for an enum type.
        /// 配合下面的 ValueDescription类使用 ;将枚举类型绑定到WPF中的ComboBox上
        /// </summary>
        public static IEnumerable<ValueDescription> GetAllValuesAndDescriptions<TEnum>() where TEnum : struct, IConvertible, IComparable, IFormattable
        {
            if (!typeof(TEnum).IsEnum)
                throw new ArgumentException("TEnum must be an Enumeration type");
            

            return from e in
                       Enum.GetValues(typeof(TEnum)).Cast<Enum>().Where(em => !Attribute.IsDefined(em.GetType().GetField(em.ToString()), typeof(HideEnumItemInUIAttribute),false))
                        select new ValueDescription() { Value = e, Description = e.GetDescription() };
        }

        /// <summary>
        /// Gets the enum value by description.
        /// </summary>
        /// <returns>The enum value.</returns>
        public static EnumType GetValueByDescription<EnumType>(string description) where EnumType : struct, IComparable, IFormattable, IConvertible
        {
            var type = typeof(EnumType);
            if (!type.IsEnum)
                throw new ArgumentException("This method is destinated for enum types only.");
            foreach (var enumName in Enum.GetNames(type))
            {
                var enumValue = Enum.Parse(type, enumName);
                if (description == ((Enum)enumValue).GetDescription())
                    return (EnumType)enumValue;
            }
            throw new ArgumentException("There is no value with this description among specified enum type values.");
        }

        /// <summary>
        /// 将Enum转换为Dict
        /// </summary>
        /// <typeparam name="TKey">枚举中元素的基础类型;默认是int</typeparam>
        /// <typeparam name="TEnum">枚举类型</typeparam>
        public static Dictionary<TKey, string> EnumToDict<TKey, TEnum>()
        {

            var dic = new Dictionary<TKey, string>();
            foreach (TKey i in Enum.GetValues(typeof(TEnum)))
            {
                string strValue = Enum.GetName(typeof(TEnum), i);
                dic.Add(i, strValue);
            }
            return dic;
        }
        #endregion
    }

    public class ValueDescription
    {
        /// <summary>
        /// 枚举子项值
        /// </summary>
        public Enum Value { get; set; }
        /// <summary>
        /// 枚举项上的特性Description中值
        /// </summary>
        public string Description { get; set; }
    }

    [AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = false)]
    [System.ComponentModel.Description("隐藏Enum子项在UI上的显示")]
    public sealed class HideEnumItemInUIAttribute : Attribute
    {
        public HideEnumItemInUIAttribute()
        {
        }

        //指示是否在该Enum绑定在的ItemsControl中,显示该Enum子项
        public bool IsShowInUI
        {
            get { return false; }
        }
    }

    public static  class EnumExtension
    {
        /// <summary>
        /// Gets the specified enum value's description. 
        /// </summary>
        /// <param name="value">The enum value.</param>
        /// <returns>The description or <c>null</c>
        /// if enum value doesn't have <see cref="DescriptionAttribute"/>.</returns>
        public static string GetDescription(this Enum value)
        {
            var fieldInfo = value.GetType().GetField(value.ToString());
            var attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);

            return attributes.Length > 0 ? attributes[0].Description : string.Empty;
        }

        /*  用法
        enum Gender
        {
            [Description("男")]
            Man,
            [Description("女")]
            Woman
        }
         Console.WriteLine(Gender.Man.GetDescription()); //输出 "男"
        Console.WriteLine(EnumHelper.GetValueByDescription<Gender>("男")); //输出 Man
         * 
         */
    }
}
